from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.api import users
from google.appengine.api import urlfetch

import utils
import logging
import urllib
import settings
import cgi
#from google.appengine.runtime.apiproxy_errors import RequestTooLargeError

class Image(db.Model):
    name        = db.StringProperty()
    desc        = db.StringProperty()
    owner       = db.UserProperty()
    secret      = db.StringProperty()
    full        = db.BlobProperty()
    full_ext    = db.StringProperty()
    small       = db.BlobProperty()
    small_ext   = db.StringProperty()
    thumb       = db.BlobProperty()
    thumb_ext   = db.StringProperty()
    published   = db.BooleanProperty()
    added       = db.DateTimeProperty(auto_now_add=True)
    modified    = db.DateTimeProperty(auto_now=True)
    
    def thumb_name(self):
        return '%s.%s' % (self.key(), self.thumb_ext)
    def small_name(self):
        return '%s_small.%s' % (self.key(), self.small_ext)
    def full_name(self):
        return '%s_full.%s' % (self.key(), self.full_ext)

import debug

class List(debug.DebugMiddleware):
    def get(self):
        #ims = Image.all().filter("published =", True).order("-modified").fetch(50)
        ims = Image.all().order("-modified").fetch(50)
        if len(ims) > 40:
            a = ims[40:]
            for r in a:
                r.delete()
            ims = ims[:40]
        
        self.response.out.write(utils.render_to_mako('gallery/gallery_list.html', {'ims':ims}) )
    
    def post(self):
        if 'file' not in self.request.POST:
            self.error(400)
            self.response.out.write("file not specified!")
            return
        
        if self.request.POST.get('file', None) is None or not self.request.POST.get('file', None).filename:
            self.redirect('./')
            return
        
        file_data = self.request.POST.get('file').file.read()
        file_name = self.request.POST.get('file').filename
        desc = cgi.escape( self.request.POST.get('desc', '')[:80] ).replace('"', '').replace("'", '')
        
        if not file_name:
            file_name = 'unknown.jpg'
        
        im = Image()
        im.name = file_name
        
        n = im.name.lower()
        ext = 'jpg'
        for e in ['jpeg', 'jpg', 'png', 'tif', 'tiff', 'gif']:
            if n.endswith(e):
                ext = e
        
        im.full_ext     = ext
        im.small_ext    = ext
        im.thumb_ext    = ext
        im.desc         = desc
        im.secret       = utils.random_string()
        im.published    = False
        im.owner        = users.get_current_user()
        im.save()
        try:
            im.full         = file_data
            im.save()
        except Exception:#RequestTooLargeError:
            pass
        
        q = urllib.urlencode({
            'id':       im.secret,
            'size':     '100x100',
            'action':   'avatar', #'thumbnail',
            'quality':  '85',
            'bgcolor':  '#EEEEEE' if ext != 'gif' else 'transparent',
            'file_name':  file_name,
            'callback': 'http://%s/gallery/%s/upload' % (settings.DOMAIN, im.key()),
        })
        resp = urlfetch.fetch('http://resizer.%s/resizer/resize?%s' % (settings.SERVICESURL,q), payload=im.full, method=urlfetch.POST, headers={}, allow_truncated=True)
        if resp.status_code != 200:
            logging.error("image %r failed to schedule resize to 100x100! fix it (%.60r)!" % (im.key(), resp.content) )
        
        q = urllib.urlencode({
            'id':       im.secret,
            'size':     '500x500',
            'action':   'resize',
            'quality':  '85',
            'bgcolor':  '#EEEEEE',
            'file_name':  file_name,
            'callback': 'http://%s/gallery/%s/upload' % (settings.DOMAIN, im.key()),
        })
        resp = urlfetch.fetch('http://resizer.%s/resizer/resize?%s' % (settings.SERVICESURL, q), payload=im.full, method=urlfetch.POST, headers={}, allow_truncated=True)
        if resp.status_code != 200:
            logging.error("image %r failed to schedule resize to 500x500! fix it (%.60r)!" % (im.key(), resp.content) )
        
        
        self.response.out.write("image %r saved. it'll be published in a while" % im.name)

class UploadImage(webapp.RequestHandler):
    def post(self, key):
        im = db.get(db.Key(key))
        if not im:
            self.error(404)
            return
        
        if self.request.POST['id'] != im.secret:
            self.error(400)
            return
            
        file_data = self.request.POST['file'].file.read()
        
        if self.request.POST['size'] == '100x100':
            im.thumb = file_data
            a = 'small'
        elif self.request.POST['size'] == '500x500':
            im.small = file_data
            a = 'full'
        
        if im.small and im.thumb:
            im.published = True
        im.save()
        logging.info("%s updated %s" % (im.key(), a) )
        self.response.out.write("ok")

mimetypes = {
    'jpeg': 'image/jpeg',
    'jpg':  'image/jpeg',
    'tiff':  'image/tiff',
    'tif':   'image/tiff',
    'gif':   'image/gif',
    'png':   'image/png',
    }
    
class ServeImage(webapp.RequestHandler):
    def get(self, key, sz, ext):
        im = db.get(db.Key(key))
        if not im:
            self.error(404)
            return
        
        if sz == '.':
            d = im.thumb
        elif sz == '_small.':
            d = im.small
        elif sz == '_full.':
            d = im.full
        else:
            raise Exception('wrong sz %r' % sz)
        
        if not d:
            d = im.full
        else:
            self.response.headers.add_header("Expires", "Thu, 01 Dec 2014 16:00:00 GMT")
        
        self.response.headers["Content-Type"] = mimetypes[ext]
        self.response.out.write(d)

class ServeDetails(webapp.RequestHandler):
    def get(self, key, detail):
        im = db.get(db.Key(key))
        if not im:
            self.error(404)
            return
        if detail == 'detail':
            self.response.out.write(utils.render_to_mako('gallery/gallery_detail.html', {'im':im}) )
        else:
            self.response.out.write(utils.render_to_mako('gallery/gallery_full.html', {'im':im}) )
        
        return